import { PoolPrefabObject } from "../core/PoolPrefabObject";

export class ResManager {

  private static _instance: ResManager = null;

  public static getInstance(): ResManager {

    if (!ResManager._instance) {

      ResManager._instance = new ResManager();
    }

    return ResManager._instance;
  }

  private m_ResPrefabRes: any = {};

  public GetResPrefab(resPath, cb): void {
    let that: ResManager = this;
    let obj: cc.Node = PoolPrefabObject.getInstance().getWithPath(resPath);
    if (obj) {
      return cb(obj);
    } else if (!this.m_ResPrefabRes.resPath) {
      //add by luoya for check
      // cc.warn( "资源没有预加载:" + resPath );
      this.loadRes(resPath, function (errorMessage, loadedResource) {
        //检查资源加载
        if (errorMessage) {
          //cc.log( '载入预制资源失败, 原因:' + errorMessage );
          return;
        }
        if (!(loadedResource instanceof cc.Prefab)) {
          //cc.log( '你载入的不是预制资源!' );
          return;
        }

        PoolPrefabObject.getInstance().initializePrefabPoolWithPath(resPath, loadedResource);
        cb(PoolPrefabObject.getInstance().getWithPath(resPath));

        that.m_ResPrefabRes.resPath = false;
      });
    }
  }

  public GetPrefabNoPool(resPath, cb) {
    this.loadRes(resPath, function (errorMessage, loadedResource) {
      //检查资源加载
      if (errorMessage) {
        //cc.log( '载入预制资源失败, 原因:' + errorMessage );
        return;
      }
      if (!(loadedResource instanceof cc.Prefab)) { /*cc.log( '你载入的不是预制资源!' ); return;*/ }

      //cc.log('加入预制:',loadedResource);
      //开始实例化预制资源
      var playerPrefab = cc.instantiate(loadedResource);
      cb(playerPrefab)
    });

  }

  /**
   * 加载资源
   * @param param_a url 资源路径
   * @param param_b 资源类型 或 加载完成回调
   * @param param_c 加载完成回调 或 加载进度回调
   * @param param_d 加载完成回调
   */
  public loadRes(param_a: any, param_b: any, param_c: any = null, param_d: any = null): void {

    // console.log(param_a)
    let that: ResManager = this;

    if (!param_c && !param_d && typeof (param_a) == "string" && typeof (param_b) == "function") {

      cc.resources.load(param_a, function (err: any, res: any) {

        if (param_b) param_b(err, res);

        that.addReferenceCount(res);
      });
    } else if (!param_d && typeof (param_a) == "string" && typeof (param_b) == "function" && typeof (param_c) == "function") {

      cc.resources.load(param_a, param_b, function (err, res) {

        if (param_c) param_c(err, res);

        that.addReferenceCount(res);
      });
    } else if (typeof (param_a) == "string" && typeof (param_b) == 'function' && typeof (param_c) == 'function' && typeof (param_d) == 'function') {

      cc.resources.load(param_a, param_b, function (completedCount: number, totalCount: number, item: any) {

        if (param_c) param_c(completedCount, totalCount, item);
      }, function (err, res) {

        if (param_d) param_d(err, res);

        that.addReferenceCount(res);
      })
    }
  }

  private dict: any = {};

  /**
   * 添加资源引用计数
   * @param obj 
   */
  private addReferenceCount(obj: any): void {

    if (!obj || !obj._uuid) return;

    let list: Array<string> = cc.assetManager.dependUtil.getDepsRecursively(obj._uuid);

    for (let k: number = 0; k < list.length; ++k) {

      let key = list[k]

      if (!key) continue;

      this.dict[list[k]] = !this.dict[list[k]] ? 0 : this.dict[list[k]];

      ++this.dict[list[k]];
    }

    // cc.log(Object.keys(this.dict).length, "this.dict.length");
  }

  /**
   * 释放资源
   * @param uidStrList 资源列表
   */
  public destroyAssets(uidStrList: string[]): void {

    for (let k: number = 0; k < uidStrList.length; ++k) {

      let key: string = uidStrList[k];

      if (this.dict[key] < 2) {

        --this.dict[key];

        cc.resources.release(key);
      }
    }
  }
}